﻿using System;
using System.Collections;
using System.Collections.Generic;

using zijian666.Abstractions;
using zijian666.Convertor;
using zijian666.Core;
using zijian666.ConvertExtensions;

namespace zijian666.Factory;

/// <summary>
/// 字典转换器 <seealso cref="DictionaryConvertor{TDictionary, TKey, TValue}"/> 工厂
/// </summary>
public sealed class DictionaryConvertorFactory : IConvertorFactory
{
    /// <inheritdoc/>
    public MatchedConvertor<T> Create<T>()
    {
        // 1. 完全匹配 MacthedType.Equals
        // 2. 可实例化, 并且实现 IDictionary<TKey, TValue?>  MacthedType.TryCreate
        // 3. 不可实例化, 但是是 Dictionary<TKey, TValue> 的接口或父类  MacthedType.Acceptable

        var type = typeof(T);
        var genericArgs = type.GetGenericArguments(typeof(IDictionary<,>));
        if (genericArgs is not null)
        {
            var matchedType = type.MatchType(typeof(Dictionary<,>).MakeGenericType(genericArgs), typeof(IDictionary<,>).MakeGenericType(genericArgs));

            switch (matchedType)
            {
                case MacthedType.Equals:
                    var convertor1 = (IConvertor<T>)Activator.CreateInstance(typeof(DictionaryConvertor<,,>).MakeGenericType(type, genericArgs[0], genericArgs[1]))!;
                    return new MatchedConvertor<T>(convertor1, MacthedType.Equals);
                case MacthedType.Acceptable:
                    var convertor2 = (IConvertor<T>)Activator.CreateInstance(typeof(DictionaryConvertor<,,>).MakeGenericType(type, genericArgs[0], genericArgs[1]))!;
                    return new MatchedConvertor<T>(convertor2, MacthedType.Acceptable);
                case MacthedType.TryCreate:
                    var convertor3 = (IConvertor<T>)Activator.CreateInstance(typeof(DictionaryConvertor<,,>).MakeGenericType(type, genericArgs[0], genericArgs[1]))!;
                    return new MatchedConvertor<T>(convertor3, MacthedType.TryCreate);
                case MacthedType.NotMatched:
                default:
                    break;
            }
        }

        switch (type.MatchType(typeof(Hashtable), typeof(IDictionary)))
        {
            case MacthedType.Equals:
                var convertor1 = (IConvertor<T>)Activator.CreateInstance(typeof(HashtableConvertor<>).MakeGenericType(type))!;
                return new MatchedConvertor<T>(convertor1, MacthedType.Equals);
            case MacthedType.Acceptable:
                if (typeof(IDictionary).IsAssignableFrom(type))
                {
                    var convertor2 = (IConvertor<T>)Activator.CreateInstance(typeof(HashtableConvertor<>).MakeGenericType(type))!;
                    return new MatchedConvertor<T>(convertor2, MacthedType.Acceptable);
                }
                break;
            case MacthedType.TryCreate:
                var convertor3 = (IConvertor<T>)Activator.CreateInstance(typeof(HashtableConvertor<>).MakeGenericType(type))!;
                return new MatchedConvertor<T>(convertor3, MacthedType.TryCreate);
            case MacthedType.NotMatched:
            default:
                break;
        }

        return default;
    }
}
